import $store from "@/store";
import {
	jbConfig,
	appPlatform,
	localStorageKey,
	baseURL,
	devMode
} from "@/config/index";
import {
	toast
} from "../utils/index";
// 是否显示日志打印
const openLog = devMode;
// 是否可配置显示loading
const openLoadingAlways = false;

// 请求方式
export const METHOD = {
	POST: "POST",
	GET: "GET"
};
const errorMessage = {
	success: "成功",
	fail: "失败",
	unlogin: "登录异常",
	error: "发生异常",
	neterror: "网络异常",
	loading: "加载中...",
	loadfail: "加载失败"
};

//code 和后台接口对应
export const errorCode = {
	"4000": "系统异常",
	"4004": "尚未登录",
	"4005": "JWT过期处理",
	"4030": "refreshjwt过期",
	"4080": "新用户需要注册"
};

const _fetchBase = (myConfig, times = 0) => {
	return new Promise((resolve, reject) => {
		let params = {};
		if (myConfig.params) {
			for (let key in myConfig.params) {
				if (
					myConfig.params[key] !== null &&
					myConfig.params[key] !== undefined
				) {
					params[key] = myConfig.params[key];
				}
			}
		}
		if (myConfig.loading) {
			uni.showLoading({
				title: "加载中",
				mask: true
			});
		}

		let customHeader = {
			platform: appPlatform
		};
		//添加后端api需要的请求头
		if (jbConfig.ENABLE) {
			customHeader[jbConfig.JBOLT_API_REQUEST] = "true";
			customHeader[jbConfig.JBOLT_APPID_KEY] = jbConfig.APPID;
		}

		let token = uni.getStorageSync(localStorageKey.token);
		let refreshToken = uni.getStorageSync(localStorageKey.refreshToken);
		if (myConfig.auth) {
			if (jbConfig.ENABLE) {
				if (myConfig.withRefreshJwt) {
					customHeader[jbConfig.JBOLT_REFRESH_JWT_KEY] = refreshToken;
				} else {
					customHeader[jbConfig.JBOLT_JWT_KEY] = token;
				}
				if (jbConfig.JBOLT_JWT_CHECKSIGN) {
					let jbsign = createSignature(false);
					customHeader[jbConfig.JBOLT_JWT_SIGNATURE_KEY] = jbsign.signature;
					customHeader[jbConfig.JBOLT_JWT_TIMESTAMP_KEY] = jbsign.timestamp;
					customHeader[jbConfig.JBOLT_JWT_NONCE_KEY] = jbsign.nonce;
				}
			} else {
				customHeader["token"] = token;
			}
		}
		uni.request({
			url: myConfig.apiBaseUrl + myConfig.api,
			method: myConfig.method || METHOD.POST,
			data: params,
			header: Object.assign(
				customHeader, {
					"content-type": "application/x-www-form-urlencoded;charset=utf-8",
					"X-Requested-With": "XMLHttpRequest"
				},
				myConfig.header
			),
			success: async res => {
				let resHeader = res.header;
				let resData = res.data;
				if (myConfig.loading) {
					uni.hideLoading();
				}
				if (openLog) {
					console.log(
						`---------------api 请求参数--------------\n` +
						`请求地址: ${myConfig.api}\n` +
						`请求参数:\n` +
						`${JSON.stringify(myConfig.params)}\n` +
						`------------------------------------------------------`
					);
					console.log("返回结果", resData);
					console.log("------------------------------------------------------");
				}
				if (resData && resData.state == "ok") {
					//不处理预检信息
					if (resData.data && resData.data["OPTIONS"] == 1) {
						console.log("======OPTIONS SUCCESS======");
						return false;
					}
					//如果有jwt返回
					let jwt = resHeader["jboltjwt"];
					let refreshToken = resHeader["jboltrefreshjwt"];
					if (jwt) {
						resData.data = Object.assign({
								token: jwt,
								refreshToken: refreshToken
							},
							resData.data ? resData.data : {}
						);
					}
					resolve(resData.data);
					return true;
				} else if (
					resData.state == "fail" &&
					myConfig.auth &&
					(resData.code === 4030 ||
						resData.code === 4005 ||
						resData.code === 4004)
				) {
					$store.dispatch("removeToken");
					$store.dispatch("removeUserInfo");
					$store.dispatch("removeSessionKey");
					if (resData.code === 4030) {
						//refreshjwt也过期了
						$store.dispatch("removeRefreshToken");
					}

					if (myConfig.login) {
						if (times === 0) {
							let refreshRes = await $store.dispatch("refreshJwtToken");
							if (refreshRes) {
								return _fetchBase(myConfig, times + 1);
							}
						}
						toast(errorMessage.unlogin);
						setTimeout(() => {
							uni.switchTab({
								url: "/pages/index/index"
							});
						}, 1000);
					}
					return false;
				} else {
					if (!myConfig.error) {
						if (resData.msg) {
							reject(resData);
							toast(resData.msg);
						} else {
							toast(errorMessage.fail);
						}
					} else {
						reject(resData);
					}
					return false;
				}
			},
			fail(err) {
				if (myConfig.loading) {
					uni.hideLoading();
				}
				if (!myConfig.error) {
					// #ifndef H5
					toast(errorMessage.neterror);
					// #endif
				} else {
					reject(err);
				}
			}
		});
	});
};

export const fetch = myConfig => {
	const defaultConfig = {
		apiBaseUrl: baseURL,
		api: "",
		method: METHOD.POST,
		params: null,
		error: false,
		loading: true,
		auth: true,
		login: true,
		withRefreshJwt: false,
		header: {}
	};
	myConfig = Object.assign({}, defaultConfig, myConfig);
	if (openLoadingAlways) myConfig.loading = true;

	myConfig.params = myConfig.params || {};
	return new Promise(async (resolve, reject) => {
		_fetchBase(myConfig).then(
			fetchRes => {
				resolve(fetchRes);
			},
			err => {
				reject(err);
			}
		);
	});
};